package cn.cttic.base.service.impl;

import cn.cttic.app.api.enums.UserAccountType;
import cn.cttic.base.api.domain.BasePerson;
import cn.cttic.base.api.domain.BaseUser;
import cn.cttic.base.api.domain.bo.BasePersonBo;
import cn.cttic.base.api.domain.vo.BaseCompanyVo;
import cn.cttic.base.api.domain.vo.BaseCreatedUserVo;
import cn.cttic.base.api.domain.vo.BasePersonVo;
import cn.cttic.base.mapper.BaseUserMapper;
import cn.cttic.base.service.IBaseCompanyService;
import cn.cttic.base.service.IBaseUserService;
import cn.cttic.common.core.exception.base.BaseException;
import cn.cttic.common.core.service.DictService;
import cn.cttic.common.core.utils.BeanCopyUtils;
import cn.cttic.common.core.utils.MapstructUtils;
import cn.cttic.common.core.utils.StringUtils;
import cn.cttic.common.mybatis.core.page.TableDataInfo;
import cn.cttic.common.mybatis.core.page.PageQuery;
import cn.dev33.satoken.secure.BCrypt;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import cn.cttic.base.mapper.BasePersonMapper;
import cn.cttic.base.service.IBasePersonService;

import java.util.List;
import java.util.Map;
import java.util.Collection;

/**
 * 人员信息Service业务层处理
 *
 * @author Times.Studio
 * @date 2024-09-17
 */
@RequiredArgsConstructor
@Service
public class BasePersonServiceImpl implements IBasePersonService {

    private final BasePersonMapper baseMapper;

    private final IBaseCompanyService baseCompanyService;

    private final IBaseUserService baseUserService;

    private final BaseUserMapper baseUserMapper;

    private final DictService dictService;

    /**
     * 查询人员信息
     *
     * @param id 主键
     * @return 人员信息
     */
    @Override
    public BaseCreatedUserVo createSaleUser(String id) {

        List<BaseUser> saleUserList = baseUserMapper.selectList(
            new LambdaQueryWrapper<BaseUser>().eq(BaseUser::getPersonId, id).eq(BaseUser::getType, UserAccountType.SALE
                .getValue())
        );
        if (saleUserList.size() > 0) {
            throw new BaseException("基础管理", "销售用户已存在");
        } else {
            // 获取人员信息
            BasePerson basePerson = baseMapper.selectById(id);

            // 复制信息
            BaseUser baseUser = BeanCopyUtils.copy(basePerson, BaseUser.class);
            baseUser.setType(UserAccountType.SALE.getValue());
            baseUser.setPersonId(id);
            baseUser.setUserName(basePerson.getPhone());
            baseUser.setStatus(0);

            String salt = BCrypt.gensalt(12);
            String password = RandomUtil.randomString(8);
            baseUser.setSalt(salt);
            String encryptedPassword = BCrypt.hashpw(password, salt);
            baseUser.setPassword(encryptedPassword);
            baseUser.setCompanyId(basePerson.getCompanyId());

            int ret = baseUserMapper.insert(baseUser);
            if (ret > 0) {
                BaseCreatedUserVo baseCreatedUserVo = new BaseCreatedUserVo();
                baseCreatedUserVo.setUserAccountType(
                    UserAccountType.SALE.getValue()
                );
                baseCreatedUserVo.setUserName(basePerson.getPhone());
                baseCreatedUserVo.setPassword(password);
                return baseCreatedUserVo;
            } else {
                throw new BaseException("基础管理", "新增销售用户失败");
            }
        }
    }

    /**
     * 查询人员信息
     *
     * @param id 主键
     * @return 人员信息
     */
    @Override
    public BaseCreatedUserVo createInstallUser(String id) {

        List<BaseUser> saleUserList = baseUserMapper.selectList(
            new LambdaQueryWrapper<BaseUser>().eq(BaseUser::getPersonId, id).eq(BaseUser::getType, UserAccountType.INSTALL
                .getValue())
        );
        if (saleUserList.size() > 0) {
            throw new BaseException("基础管理", "安装用户已存在");
        } else {
            // 获取人员信息
            BasePerson basePerson = baseMapper.selectById(id);

            // 复制信息
            BaseUser baseUser = BeanCopyUtils.copy(basePerson, BaseUser.class);
            baseUser.setType(UserAccountType.INSTALL.getValue());
            baseUser.setPersonId(id);
            baseUser.setUserName(basePerson.getPhone());
            baseUser.setSalt("");
            baseUser.setStatus(0);

            String salt = BCrypt.gensalt(12);
            String password = RandomUtil.randomString(8);
            baseUser.setSalt(salt);
            String encryptedPassword = BCrypt.hashpw(password, salt);
            baseUser.setPassword(encryptedPassword);
            baseUser.setCompanyId(basePerson.getCompanyId());

            int ret = baseUserMapper.insert(baseUser);
            if (ret > 0) {
                BaseCreatedUserVo baseCreatedUserVo = new BaseCreatedUserVo();
                baseCreatedUserVo.setUserAccountType(
                    UserAccountType.INSTALL.getValue()
                );
                baseCreatedUserVo.setUserName(basePerson.getPhone());
                baseCreatedUserVo.setPassword(password);
                return baseCreatedUserVo;
            } else {
                throw new BaseException("基础管理", "新增安装售用户失败");
            }
        }
    }

    /**
     * 查询人员信息
     *
     * @param id 主键
     * @return 人员信息
     */
    @Override
    public BasePersonVo queryById(String id) {
        return baseMapper.selectVoById(id);
    }

    /**
     * 分页查询人员信息列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return 人员信息分页列表
     */
    @Override
    public TableDataInfo<BasePersonVo> queryPageList(BasePersonBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<BasePerson> lqw = buildQueryWrapper(bo);
        Page<BasePersonVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);

        List<BasePersonVo> voList = result.getRecords();
        voList.forEach(bcp -> {
            if (StrUtil.isNotBlank(bcp.getCompanyId())) {
                BaseCompanyVo companyVo = baseCompanyService.queryById(bcp.getCompanyId());
                if (companyVo != null) {
                    bcp.setCompanyName(companyVo.getCompanyName());
                    if (StrUtil.isNotBlank(companyVo.getChannelType())) {
                        bcp.setChannelName(dictService.getDictLabel("dict_channel_type", companyVo.getChannelType()));
                    }
                }
            }

            List<BaseUser> saleUserList = baseUserMapper.selectList(
                new LambdaQueryWrapper<BaseUser>().eq(BaseUser::getPersonId, bcp.getId()).eq(BaseUser::getType, 1)
            );
            if (saleUserList.size() > 0) {
                bcp.setHasSaleUserAccount(1);
            } else {
                bcp.setHasSaleUserAccount(0);
            }

            List<BaseUser> installUserList = baseUserMapper.selectList(
                new LambdaQueryWrapper<BaseUser>().eq(BaseUser::getPersonId, bcp.getId()).eq(BaseUser::getType, 2)
            );
            if (installUserList.size() > 0) {
                bcp.setHasInstallUserAccount(1);
            } else {
                bcp.setHasInstallUserAccount(0);
            }
        });

        result.setRecords(voList);

        return TableDataInfo.build(result);
    }

    /**
     * 查询符合条件的人员信息列表
     *
     * @param bo 查询条件
     * @return 人员信息列表
     */
    @Override
    public List<BasePersonVo> queryList(BasePersonBo bo) {
        LambdaQueryWrapper<BasePerson> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<BasePerson> buildQueryWrapper(BasePersonBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<BasePerson> lqw = Wrappers.lambdaQuery();
        lqw.orderByDesc(BasePerson::getCreateTime);
        lqw.like(StringUtils.isNotBlank(bo.getRealName()), BasePerson::getRealName, bo.getRealName());
        lqw.eq(StringUtils.isNotBlank(bo.getIdCardNo()), BasePerson::getIdCardNo, bo.getIdCardNo());
        lqw.eq(StringUtils.isNotBlank(bo.getEmail()), BasePerson::getEmail, bo.getEmail());
        lqw.eq(StringUtils.isNotBlank(bo.getAvatar()), BasePerson::getAvatar, bo.getAvatar());
        lqw.eq(StringUtils.isNotBlank(bo.getPhone()), BasePerson::getPhone, bo.getPhone());
        lqw.eq(StringUtils.isNotBlank(bo.getFront()), BasePerson::getFront, bo.getFront());
        lqw.eq(StringUtils.isNotBlank(bo.getBack()), BasePerson::getBack, bo.getBack());
        lqw.eq(StringUtils.isNotBlank(bo.getCompanyId()), BasePerson::getCompanyId, bo.getCompanyId());
        lqw.eq(bo.getGender() != null, BasePerson::getGender, bo.getGender());
        lqw.eq(bo.getBirthday() != null, BasePerson::getBirthday, bo.getBirthday());
        lqw.eq(bo.getStatus() != null, BasePerson::getStatus, bo.getStatus());
        return lqw;
    }

    /**
     * 新增人员信息
     *
     * @param bo 人员信息
     * @return 是否新增成功
     */
    @Override
    public Boolean insertByBo(BasePersonBo bo) {
        BasePerson add = MapstructUtils.convert(bo, BasePerson.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    /**
     * 修改人员信息
     *
     * @param bo 人员信息
     * @return 是否修改成功
     */
    @Override
    public Boolean updateByBo(BasePersonBo bo) {
        BasePersonVo vo = baseMapper.selectVoById(bo.getId());
        if (!vo.getPhone().equals(bo.getPhone())) {
            throw new BaseException("不可以修改手机号");
        }

        if (!vo.getCompanyId().equals(bo.getCompanyId())) {
            throw new BaseException("不可以修改所属单位");
        }

        BasePerson update = MapstructUtils.convert(bo, BasePerson.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    @Override
    public Boolean disableByBo(BasePersonBo bo) {
        return null;
    }

    @Override
    public Boolean enableByBo(BasePersonBo bo) {
        return null;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(BasePerson entity) {
        //TODO 做一些数据校验,如唯一约束
        List<BasePerson> personList = baseMapper.selectList(
            new LambdaQueryWrapper<BasePerson>().eq(BasePerson::getPhone, entity.getPhone()).eq(BasePerson::getDelFlag, 0)
        );
        if (personList.size() > 0) {
            if (personList.stream().filter( x -> !x.getId().equals(entity.getId())).findAny().isPresent()) {
                throw new BaseException("该手机号已经存在");
            }
        }
    }

    /**
     * 校验并批量删除人员信息信息
     *
     * @param ids     待删除的主键集合
     * @param isValid 是否进行有效性校验
     * @return 是否删除成功
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<String> ids, Boolean isValid) {
        if (isValid) {
            return false;
        }
        return baseMapper.deleteByIds(ids) > 0;
    }

    /**
     * 启用人员
     *
     * @param id
     * @return
     */
    @Override
    public Boolean enablePerson(String id) {

        List<BaseUser> userList = baseUserMapper.selectList(
            new LambdaQueryWrapper<BaseUser>().eq(BaseUser::getPersonId, id)
        );

        for (BaseUser user : userList) {
            if (!baseUserService.enableUser(user.getId())) {
                throw new BaseException("该人员相关用户启用失败！");
            }
        }


        return baseMapper.update(
            new LambdaUpdateWrapper<BasePerson>()
                .eq(BasePerson::getId, id)
                .set(BasePerson::getStatus, 0)
        ) > 0;
    }

    /**
     * 禁用人员
     *
     * @param id
     * @return
     */
    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    public Boolean disablePerson(String id) {

        List<BaseUser> userList = baseUserMapper.selectList(
            new LambdaQueryWrapper<BaseUser>().eq(BaseUser::getPersonId, id)
        );

        for (BaseUser user : userList) {
            if (baseUserMapper.getProcessingInstallOrderListByUser(user.getId()).size() > 0) {
                throw new BaseException("该人员仍有正在进行中的订单无法禁用！");
            }
        }
        for (BaseUser user : userList) {
            if (!baseUserService.disableUser(user.getId())) {
                throw new BaseException("该人员相关用户禁用失败！");
            }
        }

        return baseMapper.update(
            new LambdaUpdateWrapper<BasePerson>()
                .eq(BasePerson::getId, id)
                .set(BasePerson::getStatus, 1)
        ) > 0;
    }
}
